Add a GNU make jobserver implementation to Cargo
authorAlex Crichton <alex@alexcrichton.com>
Tue, 30 May 2017 04:09:53 +0000 (21:09 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 2 Jun 2017 15:06:30 +0000 (08:06 -0700)
commitcbf25a9b0ae5ac6f5b6da96e645b7fa6a75dc245
tree9620a527b2de890b1b7b452828feb822c42d75a7
parent03c0a41f97c25fc5595584bdefc38b530b4d68c3
Add a GNU make jobserver implementation to Cargo

This commit adds a GNU make jobserver implementation to Cargo, both as a client
of existing jobservers and also a creator of new jobservers. The jobserver is
actually just an IPC semaphore which manifests itself as a pipe with N bytes
of tokens on Unix and a literal IPC semaphore on Windows. The rough protocol
is then if you want to run a job you read acquire the semaphore (read a byte on
Unix or wait on the semaphore on Windows) and then you release it when you're
done.

All the hairy details of the jobserver implementation are housed in the
`jobserver` crate on crates.io instead of Cargo. This should hopefully make it
much easier for the compiler to also share a jobserver implementation
eventually.

The main tricky bit here is that on Unix and Windows acquiring a jobserver token
will block the calling thread. We need to either way for a running job to exit
or to acquire a new token when we want to spawn a new job. To handle this the
current implementation spawns a helper thread that does the blocking and sends a
message back to Cargo when it receives a token. It's a little trickier with
shutting down this thread gracefully as well but more details can be found in
the `jobserver` crate.

Unfortunately crates are unlikely to see an immediate benefit of this once
implemented. Most crates are run with a manual `make -jN` and this overrides the
jobserver in the environment, creating a new jobserver in the sub-make. If the
`-jN` argument is removed, however, then `make` will share Cargo's jobserver and
properly limit parallelism.

Closes #1744
14 files changed:
Cargo.lock
Cargo.toml
src/cargo/lib.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/custom_build.rs
src/cargo/ops/cargo_rustc/job_queue.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/config.rs
src/cargo/util/process_builder.rs
src/doc/environment-variables.md
tests/cargotest/lib.rs
tests/jobserver.rs [new file with mode: 0644]